package commInterface

import (
	"encoding/json"
	"goAdapter/setting"
	"goAdapter/utils"
	"log"
	"strconv"
	"time"

	"github.com/tarm/serial"
)

type SerialInterfaceParam struct {
	Name     string `json:"Name"`
	Mode     string `json:"Mode"`
	BaudRate string `json:"BaudRate"`
	DataBits string `json:"DataBits"` //数据位: 5, 6, 7 or 8 (default 8)
	StopBits string `json:"StopBits"` //停止位: 1 or 2 (default 1)
	Parity   string `json:"Parity"`   //校验: N - None, E - Even, O - Odd (default E),(The use of no parity requires 2 stop bits.)
	Timeout  string `json:"Timeout"`  //通信超时
	Interval string `json:"Interval"` //通信间隔
}

type CommunicationSerialTemplate struct {
	Name  string               `json:"Name"`  //接口名称
	Type  string               `json:"Type"`  //接口类型,比如serial,tcp,udp,http
	Param SerialInterfaceParam `json:"Param"` //接口参数
	Port  *serial.Port         `json:"-"`     //通信句柄
}

var CommunicationSerialMap = make([]*CommunicationSerialTemplate, 0)

func (c *CommunicationSerialTemplate) Open() bool {

	serialParam := c.Param
	serialBaud, _ := strconv.Atoi(serialParam.BaudRate)

	var serialParity serial.Parity
	switch serialParam.Parity {
	case "N":
		serialParity = serial.ParityNone
	case "O":
		serialParity = serial.ParityOdd
	case "E":
		serialParity = serial.ParityEven
	}

	var serialStop serial.StopBits
	switch serialParam.StopBits {
	case "1":
		serialStop = serial.Stop1
	case "1.5":
		serialStop = serial.Stop1Half
	case "2":
		serialStop = serial.Stop2
	}

	serialConfig := &serial.Config{
		Name:        serialParam.Name,
		Baud:        serialBaud,
		Parity:      serialParity,
		StopBits:    serialStop,
		ReadTimeout: time.Millisecond * 1,
	}

	var err error
	c.Port, err = serial.OpenPort(serialConfig)
	if err != nil {
		setting.ZAPS.Errorf("通信串口接口[%s]打开失败 %v", c.Param.Name, err)
		return false
	}
	setting.ZAPS.Debugf("通信串口接口[%s]打开成功", c.Param.Name)

	return true
}

func (c *CommunicationSerialTemplate) Close() bool {

	if c.Port == nil {
		setting.ZAPS.Errorf("通信串口接口[%s] 文件句柄不存在", c.Param.Name)
		return false
	}
	err := c.Port.Close()
	if err != nil {
		setting.ZAPS.Errorf("通信串口接口[%s]关闭失败 %v", c.Param.Name, err)
		return false
	}
	setting.ZAPS.Debugf("通信串口接口[%s]关闭成功", c.Param.Name)
	return true
}

func (c *CommunicationSerialTemplate) WriteData(data []byte) int {

	if c.Port == nil {
		setting.ZAPS.Errorf("通信串口接口[%s] 文件句柄不存在", c.Param.Name)
		return 0
	}

	cnt, err := c.Port.Write(data)
	if err != nil {
		log.Println(err)
	}

	return cnt
}

func (c *CommunicationSerialTemplate) ReadData(data []byte) int {

	if c.Port == nil {
		return 0
	}

	cnt, _ := c.Port.Read(data)

	return cnt
}

func (c *CommunicationSerialTemplate) GetName() string {
	return c.Name
}

func (c *CommunicationSerialTemplate) GetTimeOut() string {
	return c.Param.Timeout
}

func (c *CommunicationSerialTemplate) GetInterval() string {
	return c.Param.Interval
}

func (c *CommunicationSerialTemplate) GetType() int {
	return CommTypeSerial
}

func (c *CommunicationSerialTemplate) GetTypeName() string {
	return c.Type
}

func (c *CommunicationSerialTemplate) GetParam() ComInterfaceParam {
	var para ComInterfaceParam
	para.SerialParam = c.Param
	return para
}

func (c *CommunicationSerialTemplate) GetParamString() string {

	para := c.Param.BaudRate + "," + c.Param.DataBits + "," + c.Param.Parity + "," + c.Param.StopBits
	return para
}

//func NewCommunicationSerialTemplate(commName, commType string, param SerialInterfaceParam) *CommunicationSerialTemplate {
//
//	return &CommunicationSerialTemplate{
//		Param: param,
//		CommunicationTemplate: CommunicationTemplate{
//			Name: commName,
//			Type: commType,
//		},
//	}
//}

func ReadCommSerialInterfaceListFromJson() bool {

	data, err := utils.FileRead("/selfpara/commSerialInterface.json")
	if err != nil {
		setting.ZAPS.Debugf("打开通信接口[串口]配置json文件失败 %v", err)
		return false
	}
	err = json.Unmarshal(data, &CommunicationSerialMap)
	if err != nil {
		setting.ZAPS.Errorf("通信接口[串口]配置json文件格式化失败 %v", err)
		return false
	}
	setting.ZAPS.Debugf("打开通信接口[串口]配置json文件成功")
	return true
}

func WriteCommSerialInterfaceListToJson() {

	utils.DirIsExist("./selfpara")

	sJson, _ := json.Marshal(CommunicationSerialMap)
	err := utils.FileWrite("/selfpara/commSerialInterface.json", sJson)
	if err != nil {
		setting.ZAPS.Errorf("写入通信接口[串口配置]json文件 %s %v", "失败", err)
		return
	}
	setting.ZAPS.Infof("写入通信接口[串口配置]json文件 %s", "成功")
}
